<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>JS 中let 和 const 的使用</title>
    <script>
    /*
    (1).在javascript中我们通常使用var会发生变量提升，即脚本开始运行时，变量已经存在了，但是没有值，所以会输出undefined，

　　     而let不会发生变量提升,这表示在声明它之前，变量是不存在的，这时如果用到它，就会抛出一个错误。
    */

    /*
    (2).var 是函数级作用域，let是块级作用域：
    */
    {
        let a = 10;
        var b = 1;  // {} 中是一个块
    }
    function testEffectiveArea() {
       alert(b);  // 能弹出来 
       alert(a);  // 报错
    }
    
    function testVarVarible () {
        var a = [];
        for (var i =0 ; i < 10; i++){
            a[i] = function () {
                console.log(i)
            }
        }
        a[6]();  // 10   如果将 var i = 0 改成 let i=0 结果是 6

        var b = []
        for (let  i =0 ; i < 10; i++){
            b[i] = function () {
                console.log(i)
            }
        }
        b[6]();  // 10   如果将 var i = 0 改成 let i=0 结果是 6
    }
    /*
    　(3).let不允许在相同作用域内，重复声明同一个变量:
    */
    function testOneVaraibleInFunc () {
        let c = 10
        var d = 12
        let c = 13  // 报错
    }

    /*
    const声明一个只读的常量。一旦声明，常量的值就不能改变
    const命令声明的常量也是不提升，只能在声明的位置后面使用。
    const声明的常量，也与let一样不可重复声明
    对于复合类型的变量，变量名不指向数据，而是指向数据所在的地址。
    const命令只是保证变量名指向的地址不变，并不保证该地址的数据不变，
　　 所以将一个对象声明为常量必须非常小心
    */
    function testConst(){
        const t = {

        }  // 这是一个复合型的变量 
        t.prop = 123
        alert(t.prop)
        t = {

        }  // typeError： Assignment to constant variable 
    }

    </script>
</head>
<body>
    <button onclick="testEffectiveArea()">对比 let 和 var 的作用域</button>
    <button onclick="testVarVarible()">对比 let 和 var 的作用域 第二次</button>
    <button onclick="testOneVaraibleInFunc()">测试 一个变量出错</button>
    <button onclick="testConst()">测试 一个 consta 变量</button>
</body>
</body>
</html>